package today.rocky.elegantcoding.filter;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @version 1.0
 * @vlog:
 * @description:
 * @author: Rocky
 * @createDate: 2020/6/5 18:28
 */
@Component
public class MyFilter  implements Filter {
	@Autowired
	private RedisTemplate<String,Integer> redisTemplate;

	@Autowired
	private Map<String,Integer> limiterMap;
	/**
	 * key过期时间（秒）
	 */
	private final Long EXPIRE_TIME = 60L;

	/**
	 * key 前缀，防止和其他地方的key可以冲突
	 */
	private final String PREFIX = "IP:LIMIT:";


	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException,
			ServletException {

		HttpServletRequest request = (HttpServletRequest) servletRequest;
		HttpServletResponse response = (HttpServletResponse) servletResponse;
		response.setCharacterEncoding("UTF-8");
		response.setHeader("Access-Control-Allow-Origin","*");
		// 获取请求IP
		String ip = request.getHeader("X-Forwarded-For");
		if (!StringUtils.isEmpty(ip) && !"unKnow".equalsIgnoreCase(ip)) {
			//多次反向代理后会有多个ip值，第一个ip才是真实ip
			String[] ipList1 = ip.split(",");
			ip = ipList1[0];
		} else {
			ip = request.getHeader("X-Real-IP");
			if (StringUtils.isEmpty(ip) || "unKnown".equalsIgnoreCase(ip)) {
				ip = request.getRemoteAddr();
			}
		}

		String servletPath = request.getServletPath();
		if(limiterMap.containsKey(servletPath)){
			// 前缀+ip构成key
			String key = PREFIX+ip;
			//检查key是否存在，返回boolean值
			Boolean flag = redisTemplate.hasKey(key);
			if(flag!=null) {
				if (flag) {
					Integer times = redisTemplate.opsForValue().get(key);
					if (times > limiterMap.get(servletPath)) {
						request.getRequestDispatcher("/visit/errorPage").forward(request, response);
					}
					// 调用次数+1
					redisTemplate.boundValueOps(key).increment(1);
					// 设置过期时间
					redisTemplate.expire(ip, EXPIRE_TIME, TimeUnit.SECONDS);
				} else {
					// 第一次调用，所以value（调用次数）设置为1
					redisTemplate.opsForValue().set(key, 1, EXPIRE_TIME, TimeUnit.SECONDS);
				}
			}
		}
		chain.doFilter(request,response);
	}
}
